import {Dictionary} from "./types/Types";
import {
    addExtendAgentToUrl,
    appendFormParamToUrl,
    appendParamsToUrl,
    buildFullUrl,
    clientEnv,
    safeToString
} from "./function/CommonUtils";
import {IEWpsFileSubmenuItems} from "./constant/WebOfficeCons";
import {AbstractWebOffice} from "./AbstractWebOffice";

export class WpsWebOffice extends AbstractWebOffice{
    _ready:boolean=false;
    private static _pluginType:string='wps';
    private _clientEnvObj:Dictionary;
    private _pluginEle:HTMLElement|null;
    constructor(wrapperId:string, options:Dictionary) {
        super(wrapperId,options);
        const self = this;
        self.hide();
        self._clientEnvObj = clientEnv();
        window._pageofficeSelectionChangeCallBack = function (selection:any) {
            self._onWordWpsSelChange(selection);
        };
        if(self._clientEnvObj.platform=="Linux") {
            const interval_control = setInterval(function () {
                const application = self.pluginObj().Application;
                if (application && application.IsLoad()) {
                    self._officeApp= application;
                    self._pluginObj= application;
                    clearInterval(interval_control);
                    window.onbeforeunload = function () {
                        self.pluginObj().Quit();
                    };
                    self._openDocumentAfterInit();
                }
            }, 200);
        }else {
            setTimeout(()=>{
                if (!self.pluginObj().Application)
                    self._ready = true;
            },200);
            setTimeout(function () {
                self._openDocumentAfterInit();
            });

        }

    }

    protected  _createObjectHtml(objId:string):string{
        return this.options.pluginHtml;
    }

    private _openDocumentAfterInit(){
        const self=this;
        let openSuccess = false;
        if (self.options.fileDownloadUrl) {
            if("createNew"==self.options.fileDownloadUrl) {
                self.createFile().then(function (result) {
                    if (self.pluginObj().Application)
                        self._officeApp = self.pluginObj().Application;
                    self._initDocument().then(function (result) {
                        if (result.errorCode == '0')
                            self._ready = true;
                    }, function (error) {
                        console.error(error.errorMessage);
                        throw new Error(error.errorMessage);
                    });
                },function (error) {
                    console.error(error.errorMessage);
                    throw new Error(error.errorMessage);
                });
            }else {
                openSuccess = self.pluginObj().openDocumentRemote(buildFullUrl(self.options.fileDownloadUrl), false);
                if (openSuccess) {
                    if (self.pluginObj().Application)
                        self._officeApp = self.pluginObj().Application;
                    self._initDocument().then(function (result) {
                        if (result.errorCode == '0')
                            self._ready = true;
                    }, function (error) {
                        console.error(error.errorMessage);
                        throw new Error(error.errorMessage);
                    });
                }
            }
        } else {
            self._ready = true;
        }

    }



    private _buttonControlByTypeAndId(type:number, id:number, enabled:boolean) {
        const controls = this.activeDocument().CommandBars.FindControls(type, id);
        if (this._clientEnvObj.platform=='Windows') {
            if (controls.Count > 0) {
                for (let i = 1; i <= controls.Count; i++) {
                    const control = controls.Item(i);
                    control.Enabled = enabled;
                }
            }
        } else {
            if (controls.Count > 0) {
                for (let i = 1; i <= controls.Count; i++) {
                    const control = controls.GetCommandbarcontrol(i);
                    control.Enabled = enabled;
                }
            }
        }
    }
    private _getCommandBar(barName:string) {
        if (this._clientEnvObj.platform=='Windows') {
            return this.activeDocument().CommandBars.Item(barName);
        } else {
            return this.activeDocument().CommandBars.GetCommandbarByName(barName);
        }
    }
    private _getControlByName(barName:string, controlName:string) {
        const commandBar = this._getCommandBar(barName);
        if (commandBar == null || commandBar == undefined)
            return null;
        if (this._clientEnvObj.platform=='Windows') {
            return commandBar.Controls.Item(controlName);
        } else {
            const controls = commandBar.Controls;
            const count = controls.Count;
            for (let i = 1; i <= count; i++) {
                const control = controls.GetCommandbarcontrol(i);
                if (control && control.Caption == controlName) {
                    return control;
                }
            }
        }
    }

    private _initFileOpenDialog() {
        const self = this;
        const fileDialog = self.officeApp().Application.FileDialog(1);
        const firstFilter = fileDialog.Filters.Item(1);
        if (firstFilter.Description.indexOf("常用文件") == -1) {
            fileDialog.Filters.Add("常用文件", "*.wps;*.wpt;*.doc;*.dot;*.rtf;*.docx;*.pdf", 2);
            fileDialog.Filters.Delete(1);
            fileDialog.Filters.Add(firstFilter.Description, firstFilter.Extensions, 2);
        }
        return fileDialog;
    }
    private _disableSameButton(readOnly:boolean) {
        const self = this;
        if (self.pluginObj().FileSubmenuItems) {
            self.pluginObj().FileSubmenuItems &= ~IEWpsFileSubmenuItems.NEW;
            if (readOnly) {
                self.pluginObj().FileSubmenuItems &= ~IEWpsFileSubmenuItems.OPEN;
            } else {
                self.pluginObj().FileSubmenuItems |= IEWpsFileSubmenuItems.OPEN;
            }
        } else {
            //禁用"新建"菜单
            self._buttonControlByTypeAndId(1, 18, false);
            self._buttonControlByTypeAndId(1, 303, false);
            self._buttonControlByTypeAndId(1, 963, false);
            self._buttonControlByTypeAndId(1, 2520, false);
            self._buttonControlByTypeAndId(1, 3833, false);
            //禁用打印预览
            self._buttonControlByTypeAndId(1, 109, false);
            if (readOnly) {
                //禁用"打开"菜单
                self._buttonControlByTypeAndId(1, 23, false);
                self._buttonControlByTypeAndId(1, 80105, false);
                self._buttonControlByTypeAndId(1, 2000022, false);
                self._buttonControlByTypeAndId(1, 100046, false);
                //禁用分页符
                self._buttonControlByTypeAndId(1, 92101, false);
            } else {
                //启用"打开"菜单
                self._buttonControlByTypeAndId(1, 23, true);
                self._buttonControlByTypeAndId(1, 80105, true);
                self._buttonControlByTypeAndId(1, 2000022, true);
                self._buttonControlByTypeAndId(1, 100046, true);
                //启用分页符
                self._buttonControlByTypeAndId(1, 92101, true);
            }
        }
    }
    private _initDocument():Promise<any> {
        const self = this;
        return new Promise(function (resolve,reject) {
            try {
                const openMode = self.options.openMode;

                if (self.options.userName)
                    self.officeApp().UserName = self.options.userName;
                if (self.officeApp().setToolbarAllVisible) {
                    self.officeApp().setToolbarAllVisible(self.options.officeToolbars);
                }
                if (self.options.officeToolbars)
                    self._disableSameButton(openMode != "docNormalEdit");
                try {
                    self._publicDocumentInitialize();
                } catch (e) {
                    reject({errorCode: '-1', errorMessage: e});
                }
                if (self.options.jsFunction_OnWordDataRegionClick && (openMode == "docNormalEdit" || openMode == "docSubmitForm" || openMode == "docAdmin")) {
                    if (self._clientEnvObj.browser != 'ie') {
                        self.officeApp().registerEvent("DIID_ApplicationEvents4", "WindowSelectionChange", "_pageofficeSelectionChangeCallBack");
                    } else {

                    }
                }
                resolve({errorCode: '0', errorMessage: ''});
            }catch (e) {
                reject({errorCode: '-1', errorMessage: e});
            }
            // },defer.reject);

        });

    }

    public show():void {
        if(!this._pluginEle)
            this._pluginEle = this.pluginObj();
        (<HTMLElement>this._pluginEle).style.height="100%";
        (<HTMLElement>this._pluginEle).style.position="static";
    }

    public hide():void {
        if(!this._pluginEle)
            this._pluginEle = this.pluginObj();
        (<HTMLElement>this._pluginEle).style.height=(<HTMLElement>(<HTMLElement>this._pluginEle).parentNode).clientHeight+"px";
        (<HTMLElement>this._pluginEle).style.position="absolute";
        (<HTMLElement>this._pluginEle).style.left="-99999px";
    }
    private fullScreen() {
        this.officeApp().FullScreen();
    }

    public deleteBookmark(name:string):void {
        super.deleteBookmark(name);
        const that=this;
        delete that._bookmarkRange[safeToString(name).toLowerCase()];
    }

    public enableToolbars(enable:boolean=true) {
        this.options.officeToolbars = enable;
        this.officeApp().setToolbarAllVisible(enable);
    }
    public operateOriginDoc(callback:Function) {
        if (this._protectionType > -1) {
            this.activeDocument().Unprotect(this._protectPass);
        }
        callback.call(this);
        if (this._protectionType > -1) {
            this.activeDocument().Protect(this._protectionType, true, this._protectPass);
        }
    }
    public print():void {
        const that=this;
        const control = that._getControlByName("File", "打印(&P)...");
        if (control) {
            control.Execute();
        } else {
            that.officeApp().Application.PrintOut();
        }
    }
    public importFile():Promise<any> {
        const that=this;
        return new Promise<any>(function (resolve,reject) {
            if (that._clientEnvObj.platform=='Windows') {
                const fileDialog = that._initFileOpenDialog();
                if (fileDialog) {
                    const r = fileDialog.Show();
                    if (r == -1) {
                        const filePath = fileDialog.SelectedItems.Item(1);

                        that.openLocalFile(filePath,false).then(resolve,reject);
                    }
                }
            } else {
                that._getControlByName("File", "打开(&O)...").Execute();
                that._initDocument().then(resolve,reject);
            }
        })

    }
    public printPreview() {
        this.activeDocument().PrintPreview()
    }
    public closePrintPreview() {
        this.activeDocument().ClosePrintPreview();
    }

    public openRemoteFile(fileUrl:string,readOnly:boolean):Promise<any> {
        const that=this;
        return new Promise<any>(function (resolve,reject) {
            that._ready=false;
            let success = that.pluginObj().openDocumentRemote(buildFullUrl(fileUrl), readOnly);
            if (success) {
                that._initDocument().then(function (result) {
                    that._ready=true;
                    resolve(result);
                },reject);
            }
        })

    }
    public isDirty(){
        return !this.activeDocument().Saved;
    }
    public saveAs(fileName?:string) {
        this.officeApp().saveAs();
    }

    private addFileNameToUrl(url:string){
        let fileName=this.activeDocument().Name;
        const fileExtName=this.options.openMode.substr(0,3);
        if(fileName.indexOf("."+fileExtName)===-1){
            fileName+="."+fileExtName;
        }
        return appendParamsToUrl(url,"wpsFileName="+fileName);
    }

    public saveToUrl(tempUrl?:string):Promise<any> {
        const self = this;
        const url = tempUrl || self.options.saveFilePage;
        return new Promise(function (resolve,reject) {
            let unprotect = false;
            if (self._protectionType > -1) {
                unprotect = true;
                self.activeDocument().Unprotect(self._protectPass);
            }
            if (self._protectionType == 3) {
                self._deleteAllEditors();
            }
            let r = self.pluginObj().saveURL(appendFormParamToUrl(addExtendAgentToUrl(self.addFileNameToUrl(url), WpsWebOffice._pluginType)), "");
            if (self._protectionType == 3) {
                self._recoveryAllEditors();
            }
            if (r) {
                if (unprotect && self._protectionType > -1)
                    self.activeDocument().Protect(self._protectionType, true, self._protectPass);
                resolve({errorCode: "0", result: true, errorMessage: "OK"});
            } else {
                if (unprotect && self._protectionType > -1)
                    self.activeDocument().Protect(self._protectionType, true, self._protectPass);
                reject({errorCode: "-1", result: false, errorMessage: "fail!"});
            }
        });
    }
    public getAllBookmarkValue(): Object  {
        const that=this;
        const fieldData:Dictionary={}
        for (let bookmarkName in that._bookmarkRange) {
            const originName=this._lowerCaseNameToOriginMap[bookmarkName]||bookmarkName;
            const value = that.getBookmarkValue(originName);
            fieldData[originName]=value;
        }
        return fieldData;
    }


    public createFile(): Promise<any> {
        const that=this;
        return new Promise(function (resolve,reject) {
            let success:boolean=false;
            try {
                if (that._clientEnvObj.platform == "linux") {
                    resolve({errorCode: '0', errorMessage: 'OK', result: that.pluginObj().createDocument('wps')});
                } else {
                    resolve({errorCode: '0', errorMessage: 'OK', result: that.pluginObj().createDocument('uot')});
                }
            }catch (e) {
                reject({errorCode: '-1', errorMessage: e})
            }
        });
    }


    public openLocalFile(filePath: string,readOnly:boolean): Promise<any> {
        const that=this;
        return new Promise(function (resolve,reject) {
            try{
                that.pluginObj().openDocument(filePath, readOnly);
                that._initDocument().then(resolve, reject);
            }catch (e) {
                reject({errorCode:'-1',errorMessage:e,result:false});
            }
        })
    }

}